package com.mlog.njyjy.ndop.msg.relay.util;

import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.google.common.collect.ImmutableMap;
import com.mlog.njyjy.ndop.msg.common.domain.Dict;
import com.mlog.njyjy.ndop.msg.common.domain.DictItem;
import com.mlog.njyjy.ndop.msg.persistence.dao.DictRepository;
import com.mlog.njyjy.ndop.msg.relay.domain.StandardField;
import com.mlog.njyjy.ndop.msg.relay.exception.ValidateException;
import com.mlog.njyjy.ndop.msg.relay.service.ConfigLoaderService;
import com.mlog.njyjy.ndop.msg.relay.support.MustacheEngine;
import com.mlog.njyjy.ndop.share.sql.support.SqlTableUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 验证消息
 * </p>
 *
 * @author zyz
 * @version v1.0, 2020/8/3
 */
@Slf4j
@Service
public class StandardFieldValidator {

	@Autowired
	private DictRepository dictRepository;

	@Autowired
	private ConfigLoaderService configLoaderService;

	public StandardFieldValidator() {

	}

	public boolean validate(String input) {
		log.info(input);
		input = input.trim();
		JSONObject json;
		try {
			json = new JSONObject(input);
		} catch (Exception e) {
			log.error(e.getLocalizedMessage());
			throw new ValidateException(-1, e.getLocalizedMessage(), input);
		}

		List<StandardField> standardFieldList = configLoaderService.getConfig();
		if (standardFieldList == null || standardFieldList.size() == 0) {
			log.error("config of standard fields is null");
			throw new ValidateException(-1, "config of standard fields is null", input);
		}

		for (StandardField standardField : standardFieldList) {
			String name = standardField.getName();
			if (standardField.getRequired() && !standardField.getDisabled()) {
				// 字段必需且开启验证
				Object value = json.get(name);
				if (value == null) {
					throw new ValidateException(standardField, value, input);
				}
				String valueType = getObjType(value);
				if (valueType == null) {
					throw new ValidateException(standardField, value, input);
				}
				if (!valueType.equals(standardField.getValueType())) {// 数据类型验证
					throw new ValidateException(standardField, value, input);
				}

				if ("string".equals(valueType)) {
					String valStr = String.valueOf(value);
					if (StrUtil.isBlank(valStr)) {
						throw new ValidateException(standardField, value, input);
					}
					// 1. 判断字典表中是否存在 或者 2. 校验长度是否超出 正则校验内容是否正确
					String dictName = standardField.getDictName();
					if (StrUtil.isNotBlank(dictName)) {
						// 查字典
						Dict dict = dictRepository.findFirst(StrUtil.format("select * from {} where name = '{}' ",
								SqlTableUtil.getTblName(Dict.class), dictName));
						List<DictItem> dictItems = dictRepository.findItems(dict.getId());
						if (dictItems == null || dictItems.isEmpty()) {
							throw new ValidateException(standardField, value, input);
						}
						List<String> itemNames = dictItems.stream().filter(Objects::nonNull).map(DictItem::getName)
								.collect(Collectors.toList());
						if (!itemNames.contains(valStr)) {
							throw new ValidateException(standardField, value, input);
						}

					} else {
						String type = json.getStr("type");
						if (StrUtil.isNotBlank(type) && "PID".equals(name)) {
							standardField.setLength(type.length() + 16);
						}
						int length = String.valueOf(value).length();
						if (length != standardField.getLength() && 0 != standardField.getLength()) {
							throw new ValidateException(standardField, value, input);
						}
						// 正则校验
						String regex = standardField.getRegex();
						if (StrUtil.isNotBlank(regex)) {
							// 目前已知的需要渲染的只有type
							regex = MustacheEngine.renderText(regex, ImmutableMap.of("type", type));
							if (!ReUtil.contains(regex, String.valueOf(value))) {
								throw new ValidateException(standardField, value, input);
							}
						}
					}
				} else {
					// 非字符串类型 只需进行简单的正则校验
					String regex = standardField.getRegex();
					if (!ReUtil.contains(regex, String.valueOf(value))) {
						throw new ValidateException(standardField, value, input);
					}
				}
			}
		}
		return true;
	}

	/**
	 * 数据类型
	 */
	public static String getObjType(Object object1) {

		if (object1 instanceof Integer) {
			return "int";
		} else if (object1 instanceof Long) {
			return "long";
		} else if (object1 instanceof Double) {
			return "double";
		} else if (object1 instanceof Float) {
			return "float";
		} else if (object1 instanceof String) {
			return "string";
		} else {
			log.error("unknown type, or yourself type");
		}
		return null;
	}
}
